package oop.controller.api;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import oop.controller.ControllerServlet;
import oop.controller.action.Action;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.oreilly.servlet.ParameterList;
import com.oreilly.servlet.ParameterParser;

public abstract class APIAction implements Action {

	protected ControllerServlet controller;
	protected HttpServletRequest request;
	protected HttpServletResponse response;
	private ParameterList params;
	
	@Override
	public ControllerServlet getController() {
		return controller;
	}

	@Override
	public String getNextAction() {
		return null;
	}

	@Override
	public String getPreviousQuery() {
		return null;
	}

	@Override
	public HttpServletRequest getRequest() {
		return request;
	}

	protected ParameterList params() {
		if (params == null) {
			params = new ParameterParser(request);
		}
		return params;
	}

	@Override
	public HttpServletResponse getResponse() {
		return response;
	}

	@Override
	public boolean isPreventForward() {
		return true;
	}

	@Override
	public void perform() throws IOException {
		Object result;
		try {
			result = performImpl();
		} catch (Exception e) {
			result = new APIExceptionResult(e);
		}
		if (result instanceof String) {
			response.getWriter().write((String) result);
		} else if (result instanceof JsonElement) {
			response.getWriter().write(result.toString());
		} else {
			new Gson().toJson(result, response.getWriter());
		}
	}
	
	protected abstract Object performImpl() throws Exception;

	@Override
	public void setController(ControllerServlet controller) {
		this.controller = controller;
	}

	@Override
	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	@Override
	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	/**
	 * Create a result object when the action is successful.
	 * @return JSON result object
	 */
	protected JsonObject success() {
		return new JsonObject().addProperty("status",
				APIResult.STATUS_SUCCESSFUL);
	}
	
	/**
	 * Create a result object when the action is failed.
	 * @return JSON result object
	 */
	protected JsonObject fail() {
		return new JsonObject().addProperty("status",
				APIResult.STATUS_FAILED);
	}

}
